else if (STN)
AddrOp = STN->getOperand(2);
+ // If the address points a frame object or a frame object with an offset,
+ // we need to check the object alignment.
short Imm = 0;
- if (AddrOp.getOpcode() == ISD::ADD) {
+ if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(
+ AddrOp.getOpcode() == ISD::ADD ? AddrOp.getOperand(0) :
+ AddrOp)) {
// If op0 is a frame index that is under aligned, we can't do it either,
// because it is translated to r31 or r1 + slot + offset. We won't know the
// slot number until the stack frame is finalized.
- if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(AddrOp.getOperand(0))) {
- const MachineFrameInfo &MFI = CurDAG->getMachineFunction().getFrameInfo();
- unsigned SlotAlign = MFI.getObjectAlignment(FI->getIndex());
- if ((SlotAlign % Val) != 0)
- return false;
- }
- return isIntS16Immediate(AddrOp.getOperand(1), Imm) && !(Imm % Val);
+ const MachineFrameInfo &MFI = CurDAG->getMachineFunction().getFrameInfo();
+ unsigned SlotAlign = MFI.getObjectAlignment(FI->getIndex());
+ if ((SlotAlign % Val) != 0)
+ return false;
+
+ // If we have an offset, we need further check on the offset.
+ if (AddrOp.getOpcode() != ISD::ADD)
+ return true;
}
+ if (AddrOp.getOpcode() == ISD::ADD)
+ return isIntS16Immediate(AddrOp.getOperand(1), Imm) && !(Imm % Val);
+
// If the address comes from the outside, the offset will be zero.
return AddrOp.getOpcode() == ISD::CopyFromReg;
}
}
declare void @sink(...)
+
+; stack object should be accessed using D-form load/store instead of X-form
+define signext i32 @func1() {
+; CHECK-LABEL: @func1
+; CHECK-NOT: stxvx
+; CHECK: stxv {{[0-9]+}}, {{[0-9]+}}(1)
+; CHECK-NOT: stxvx
+; CHECK: blr
+entry:
+ %a = alloca [4 x i32], align 4
+ %0 = bitcast [4 x i32]* %a to i8*
+ call void @llvm.memset.p0i8.i64(i8* nonnull align 4 %0, i8 0, i64 16, i1 false)
+ %arraydecay = getelementptr inbounds [4 x i32], [4 x i32]* %a, i64 0, i64 0
+ %call = call signext i32 @callee(i32* nonnull %arraydecay) #3
+ ret i32 %call
+}
+
+; stack object should be accessed using D-form load/store instead of X-form
+define signext i32 @func2() {
+; CHECK-LABEL: @func2
+; CHECK-NOT: stxvx
+; CHECK: stxv [[ZEROREG:[0-9]+]], {{[0-9]+}}(1)
+; CHECK: stxv [[ZEROREG]], {{[0-9]+}}(1)
+; CHECK: stxv [[ZEROREG]], {{[0-9]+}}(1)
+; CHECK: stxv [[ZEROREG]], {{[0-9]+}}(1)
+; CHECK-NOT: stxvx
+; CHECK: blr
+entry:
+ %a = alloca [16 x i32], align 4
+ %0 = bitcast [16 x i32]* %a to i8*
+ call void @llvm.memset.p0i8.i64(i8* nonnull align 4 %0, i8 0, i64 64, i1 false)
+ %arraydecay = getelementptr inbounds [16 x i32], [16 x i32]* %a, i64 0, i64 0
+ %call = call signext i32 @callee(i32* nonnull %arraydecay) #3
+ ret i32 %call
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #1
+declare signext i32 @callee(i32*) local_unnamed_addr #2