#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/LowLevelType.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
#include <queue>
/// \return The newly created instruction.
MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &BB);
+ /// Build and insert \p Res = G_CONSTANT \p Val
+ ///
+ /// G_CONSTANT is an integer constant with the specified size and value. \p
+ /// Val will be extended or truncated to the size of \p Reg.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res must be a generic virtual register with scalar or pointer
+ /// type.
+ ///
+ /// \return The newly created instruction.
+ MachineInstrBuilder buildConstant(unsigned Res, const ConstantInt &Val);
+
/// Build and insert \p Res = G_CONSTANT \p Val
///
/// G_CONSTANT is an integer constant with the specified size and value.
else if (isa<UndefValue>(C))
EntryBuilder.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(Reg);
else if (isa<ConstantPointerNull>(C))
- EntryBuilder.buildInstr(TargetOpcode::G_CONSTANT)
- .addDef(Reg)
- .addImm(0);
+ EntryBuilder.buildConstant(Reg, 0);
else if (auto GV = dyn_cast<GlobalValue>(&C))
EntryBuilder.buildGlobalValue(Reg, GV);
else if (auto CE = dyn_cast<ConstantExpr>(&C)) {
}
case TargetOpcode::G_CONSTANT: {
unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
- MIRBuilder.buildConstant(DstExt, MI.getOperand(1).getImm());
+ MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
MI.eraseFromParent();
return Legalized;
return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op);
}
-MachineInstrBuilder MachineIRBuilder::buildConstant(unsigned Res, int64_t Val) {
- assert(MRI->getType(Res).isScalar() && "invalid operand type");
+MachineInstrBuilder MachineIRBuilder::buildConstant(unsigned Res,
+ const ConstantInt &Val) {
+ LLT Ty = MRI->getType(Res);
+
+ assert(Ty.isScalar() || Ty.isPointer() && "invalid operand type");
+
+ const ConstantInt *NewVal = &Val;
+ if (Ty.getSizeInBits() != Val.getBitWidth())
+ NewVal = ConstantInt::get(MF->getFunction()->getContext(),
+ Val.getValue().sextOrTrunc(Ty.getSizeInBits()));
+
+ return buildInstr(TargetOpcode::G_CONSTANT).addDef(Res).addCImm(NewVal);
+}
- return buildInstr(TargetOpcode::G_CONSTANT).addDef(Res).addImm(Val);
+MachineInstrBuilder MachineIRBuilder::buildConstant(unsigned Res,
+ int64_t Val) {
+ auto IntN = IntegerType::get(MF->getFunction()->getContext(),
+ MRI->getType(Res).getSizeInBits());
+ ConstantInt *CI = ConstantInt::get(IntN, Val, true);
+ return buildConstant(Res, *CI);
}
MachineInstrBuilder MachineIRBuilder::buildFConstant(unsigned Res,
// FIXME: Is going through int64_t always correct?
ImmOp.ChangeToImmediate(
ImmOp.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
+ } else {
+ uint64_t Val = I.getOperand(1).getCImm()->getZExtValue();
+ I.getOperand(1).ChangeToImmediate(Val);
}
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
# CHECK: %0 = MOVi32imm 42
body: |
bb.0:
- %0(s32) = G_CONSTANT 42
+ %0(s32) = G_CONSTANT i32 42
...
---
# CHECK: %0 = MOVi64imm 1234567890123
body: |
bb.0:
- %0(s64) = G_CONSTANT 1234567890123
+ %0(s64) = G_CONSTANT i64 1234567890123
...
---
bb.0:
liveins: %x0
%0(p0) = COPY %x0
- %1(s64) = G_CONSTANT 42
+ %1(s64) = G_CONSTANT i64 42
%2(p0) = G_GEP %0, %1(s64)
...
; rest of the entry block.
; CHECK-LABEL: name: constant_int
; CHECK: [[IN:%[0-9]+]](s32) = COPY %w0
-; CHECK: [[ONE:%[0-9]+]](s32) = G_CONSTANT 1
+; CHECK: [[ONE:%[0-9]+]](s32) = G_CONSTANT i32 1
; CHECK: G_BR
; CHECK: [[SUM1:%[0-9]+]](s32) = G_ADD [[IN]], [[ONE]]
}
; CHECK-LABEL: name: constant_int_start
-; CHECK: [[TWO:%[0-9]+]](s32) = G_CONSTANT 2
-; CHECK: [[ANSWER:%[0-9]+]](s32) = G_CONSTANT 42
+; CHECK: [[TWO:%[0-9]+]](s32) = G_CONSTANT i32 2
+; CHECK: [[ANSWER:%[0-9]+]](s32) = G_CONSTANT i32 42
; CHECK: [[RES:%[0-9]+]](s32) = G_ADD [[TWO]], [[ANSWER]]
define i32 @constant_int_start() {
%res = add i32 2, 42
}
; CHECK-LABEL: name: test_constant_inttoptr
-; CHECK: [[ONE:%[0-9]+]](s64) = G_CONSTANT 1
+; CHECK: [[ONE:%[0-9]+]](s64) = G_CONSTANT i64 1
; CHECK: [[PTR:%[0-9]+]](p0) = G_INTTOPTR [[ONE]]
; CHECK: %x0 = COPY [[PTR]]
define i8* @test_constant_inttoptr() {
; This failed purely because the Constant -> VReg map was kept across
; functions, so reuse the "i64 1" from above.
; CHECK-LABEL: name: test_reused_constant
-; CHECK: [[ONE:%[0-9]+]](s64) = G_CONSTANT 1
+; CHECK: [[ONE:%[0-9]+]](s64) = G_CONSTANT i64 1
; CHECK: %x0 = COPY [[ONE]]
define i64 @test_reused_constant() {
ret i64 1
}
; CHECK-LABEL: name: test_constant_null
-; CHECK: [[NULL:%[0-9]+]](p0) = G_CONSTANT 0
+; CHECK: [[NULL:%[0-9]+]](p0) = G_CONSTANT i64 0
; CHECK: %x0 = COPY [[NULL]]
define i8* @test_constant_null() {
ret i8* null
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w0
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
-; CHECK: [[ZERO:%[0-9]+]](s1) = G_CONSTANT 0
+; CHECK: [[ZERO:%[0-9]+]](s1) = G_CONSTANT i1 false
; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_UADDE [[LHS]], [[RHS]], [[ZERO]]
; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32
; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0)
; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w0
; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w1
; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2
-; CHECK: [[ZERO:%[0-9]+]](s1) = G_CONSTANT 0
+; CHECK: [[ZERO:%[0-9]+]](s1) = G_CONSTANT i1 false
; CHECK: [[VAL:%[0-9]+]](s32), [[OVERFLOW:%[0-9]+]](s1) = G_USUBE [[LHS]], [[RHS]], [[ZERO]]
; CHECK: [[RES:%[0-9]+]](s64) = G_SEQUENCE [[VAL]](s32), 0, [[OVERFLOW]](s1), 32
; CHECK: G_STORE [[RES]](s64), [[ADDR]](p0)
; CHECK-LABEL: name: test_objectsize
; CHECK: [[ADDR0:%[0-9]+]](p0) = COPY %x0
; CHECK: [[ADDR1:%[0-9]+]](p0) = COPY %x1
-; CHECK: {{%[0-9]+}}(s64) = G_CONSTANT -1
-; CHECK: {{%[0-9]+}}(s64) = G_CONSTANT 0
-; CHECK: {{%[0-9]+}}(s32) = G_CONSTANT -1
-; CHECK: {{%[0-9]+}}(s32) = G_CONSTANT 0
+; CHECK: {{%[0-9]+}}(s64) = G_CONSTANT i64 -1
+; CHECK: {{%[0-9]+}}(s64) = G_CONSTANT i64 0
+; CHECK: {{%[0-9]+}}(s32) = G_CONSTANT i32 -1
+; CHECK: {{%[0-9]+}}(s32) = G_CONSTANT i32 0
%size64.0 = call i64 @llvm.objectsize.i64(i8* %addr0, i1 0)
%size64.intmin = call i64 @llvm.objectsize.i64(i8* %addr0, i1 1)
%size32.0 = call i32 @llvm.objectsize.i32(i8* %addr0, i1 0)
}
; CHECK-LABEL: name: test_call_stack
-; CHECK: [[C42:%[0-9]+]](s8) = G_CONSTANT 42
-; CHECK: [[C12:%[0-9]+]](s8) = G_CONSTANT 12
+; CHECK: [[C42:%[0-9]+]](s8) = G_CONSTANT i8 42
+; CHECK: [[C12:%[0-9]+]](s8) = G_CONSTANT i8 12
; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
-; CHECK: [[C42_OFFS:%[0-9]+]](s64) = G_CONSTANT 0
+; CHECK: [[C42_OFFS:%[0-9]+]](s64) = G_CONSTANT i64 0
; CHECK: [[C42_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[C42_OFFS]](s64)
; CHECK: G_STORE [[C42]](s8), [[C42_LOC]](p0) :: (store 1 into stack, align 0)
; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
-; CHECK: [[C12_OFFS:%[0-9]+]](s64) = G_CONSTANT 1
+; CHECK: [[C12_OFFS:%[0-9]+]](s64) = G_CONSTANT i64 1
; CHECK: [[C12_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[C12_OFFS]](s64)
; CHECK: G_STORE [[C12]](s8), [[C12_LOC]](p0) :: (store 1 into stack + 1, align 0)
; CHECK: BL @test_stack_slots
; CHECK-LABEL: name: test_multiple_args
; CHECK: [[IN:%[0-9]+]](s64) = COPY %x0
-; CHECK: [[ANSWER:%[0-9]+]](s32) = G_CONSTANT 42
+; CHECK: [[ANSWER:%[0-9]+]](s32) = G_CONSTANT i32 42
; CHECK: %w0 = COPY [[ANSWER]]
; CHECK: %x1 = COPY [[IN]]
; CHECK: BL @multiple_args_callee, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %w0, implicit %x1
}
; CHECK-LABEL: name: test_call_stack
-; CHECK: [[C42:%[0-9]+]](s64) = G_CONSTANT 42
-; CHECK: [[C12:%[0-9]+]](s64) = G_CONSTANT 12
+; CHECK: [[C42:%[0-9]+]](s64) = G_CONSTANT i64 42
+; CHECK: [[C12:%[0-9]+]](s64) = G_CONSTANT i64 12
; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
-; CHECK: [[C42_OFFS:%[0-9]+]](s64) = G_CONSTANT 0
+; CHECK: [[C42_OFFS:%[0-9]+]](s64) = G_CONSTANT i64 0
; CHECK: [[C42_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[C42_OFFS]](s64)
; CHECK: G_STORE [[C42]](s64), [[C42_LOC]](p0) :: (store 8 into stack, align 0)
; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
-; CHECK: [[C12_OFFS:%[0-9]+]](s64) = G_CONSTANT 8
+; CHECK: [[C12_OFFS:%[0-9]+]](s64) = G_CONSTANT i64 8
; CHECK: [[C12_LOC:%[0-9]+]](p0) = G_GEP [[SP]], [[C12_OFFS]](s64)
; CHECK: G_STORE [[C12]](s64), [[C12_LOC]](p0) :: (store 8 into stack + 8, align 0)
; CHECK: BL @test_stack_slots
; CHECK: %w1 = COPY [[SEL_RET]]
; CHECK: bb.2:
-; CHECK: [[SEL:%[0-9]+]](s32) = G_CONSTANT 1
+; CHECK: [[SEL:%[0-9]+]](s32) = G_CONSTANT i32 1
; CHECK: {{%[0-9]+}}(s128) = G_INSERT {{%[0-9]+}}(s128), [[SEL]](s32), 64
define { i8*, i32 } @bar() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: name: test_scalar_add_big
; CHECK-NOT: G_EXTRACT
; CHECK-NOT: G_SEQUENCE
- ; CHECK-DAG: [[CARRY0_32:%.*]](s32) = G_CONSTANT 0
+ ; CHECK-DAG: [[CARRY0_32:%.*]](s32) = G_CONSTANT i32 0
; CHECK-DAG: [[CARRY0:%[0-9]+]](s1) = G_TRUNC [[CARRY0_32]]
; CHECK: [[RES_LO:%.*]](s64), [[CARRY:%.*]](s1) = G_UADDE %0, %2, [[CARRY0]]
; CHECK: [[RES_HI:%.*]](s64), {{%.*}}(s1) = G_UADDE %1, %3, [[CARRY]]
body: |
bb.0.entry:
; CHECK-LABEL: name: test_constant
- ; CHECK: [[TMP:%[0-9]+]](s32) = G_CONSTANT 0
+ ; CHECK: [[TMP:%[0-9]+]](s32) = G_CONSTANT i32 0
; CHECK: %0(s1) = G_TRUNC [[TMP]]
- ; CHECK: [[TMP:%[0-9]+]](s32) = G_CONSTANT 42
+ ; CHECK: [[TMP:%[0-9]+]](s32) = G_CONSTANT i32 42
; CHECK: %1(s8) = G_TRUNC [[TMP]]
- ; CHECK: [[TMP:%[0-9]+]](s32) = G_CONSTANT 65535
+ ; CHECK: [[TMP:%[0-9]+]](s32) = G_CONSTANT i32 -1
; CHECK: %2(s16) = G_TRUNC [[TMP]]
- ; CHECK: %3(s32) = G_CONSTANT -1
- ; CHECK: %4(s64) = G_CONSTANT 1
- ; CHECK: %5(s64) = G_CONSTANT 0
+ ; CHECK: %3(s32) = G_CONSTANT i32 -1
+ ; CHECK: %4(s64) = G_CONSTANT i64 1
+ ; CHECK: %5(s64) = G_CONSTANT i64 0
- %0(s1) = G_CONSTANT 0
- %1(s8) = G_CONSTANT 42
- %2(s16) = G_CONSTANT 65535
- %3(s32) = G_CONSTANT -1
- %4(s64) = G_CONSTANT 1
- %5(s64) = G_CONSTANT 0
+ %0(s1) = G_CONSTANT i1 0
+ %1(s8) = G_CONSTANT i8 42
+ %2(s16) = G_CONSTANT i16 65535
+ %3(s32) = G_CONSTANT i32 -1
+ %4(s64) = G_CONSTANT i64 1
+ %5(s64) = G_CONSTANT i64 0
...
---
define %type* @first_offset_const(%type* %addr) {
; CHECK-LABEL: name: first_offset_const
; CHECK: [[BASE:%[0-9]+]](p0) = COPY %x0
-; CHECK: [[OFFSET:%[0-9]+]](s64) = G_CONSTANT 32
+; CHECK: [[OFFSET:%[0-9]+]](s64) = G_CONSTANT i64 32
; CHECK: [[RES:%[0-9]+]](p0) = G_GEP [[BASE]], [[OFFSET]](s64)
; CHECK: %x0 = COPY [[RES]](p0)
; CHECK-LABEL: name: first_offset_variable
; CHECK: [[BASE:%[0-9]+]](p0) = COPY %x0
; CHECK: [[IDX:%[0-9]+]](s64) = COPY %x1
-; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT 32
+; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT i64 32
; CHECK: [[OFFSET:%[0-9]+]](s64) = G_MUL [[SIZE]], [[IDX]]
; CHECK: [[STEP0:%[0-9]+]](p0) = G_GEP [[BASE]], [[OFFSET]](s64)
; CHECK: [[RES:%[0-9]+]](p0) = COPY [[STEP0]](p0)
; CHECK-LABEL: name: first_offset_ext
; CHECK: [[BASE:%[0-9]+]](p0) = COPY %x0
; CHECK: [[IDX32:%[0-9]+]](s32) = COPY %w1
-; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT 32
+; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT i64 32
; CHECK: [[IDX64:%[0-9]+]](s64) = G_SEXT [[IDX32]](s32)
; CHECK: [[OFFSET:%[0-9]+]](s64) = G_MUL [[SIZE]], [[IDX64]]
; CHECK: [[STEP0:%[0-9]+]](p0) = G_GEP [[BASE]], [[OFFSET]](s64)
; CHECK-LABEL: name: const_then_var
; CHECK: [[BASE:%[0-9]+]](p0) = COPY %x0
; CHECK: [[IDX:%[0-9]+]](s64) = COPY %x1
-; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_CONSTANT 272
+; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_CONSTANT i64 272
; CHECK: [[BASE1:%[0-9]+]](p0) = G_GEP [[BASE]], [[OFFSET1]](s64)
-; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT 4
+; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT i64 4
; CHECK: [[OFFSET2:%[0-9]+]](s64) = G_MUL [[SIZE]], [[IDX]]
; CHECK: [[BASE2:%[0-9]+]](p0) = G_GEP [[BASE1]], [[OFFSET2]](s64)
; CHECK: [[RES:%[0-9]+]](p0) = COPY [[BASE2]](p0)
; CHECK-LABEL: name: var_then_const
; CHECK: [[BASE:%[0-9]+]](p0) = COPY %x0
; CHECK: [[IDX:%[0-9]+]](s64) = COPY %x1
-; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT 64
+; CHECK: [[SIZE:%[0-9]+]](s64) = G_CONSTANT i64 64
; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_MUL [[SIZE]], [[IDX]]
; CHECK: [[BASE1:%[0-9]+]](p0) = G_GEP [[BASE]], [[OFFSET1]](s64)
-; CHECK: [[OFFSET2:%[0-9]+]](s64) = G_CONSTANT 40
+; CHECK: [[OFFSET2:%[0-9]+]](s64) = G_CONSTANT i64 40
; CHECK: [[BASE2:%[0-9]+]](p0) = G_GEP [[BASE1]], [[OFFSET2]](s64)
; CHECK: %x0 = COPY [[BASE2]](p0)